package wechat.app.bean.message;

import com.alibaba.fastjson.JSON;
import org.dom4j.DocumentException;
import org.w3c.dom.Document;
import util.Common;
import util.DataFormatUtil;
import wechat.app.aes.AesException;
import wechat.app.aes.WXBizMsgCrypt;
import wechat.app.bean.message.category.card.CardPayOrderEvent;

import java.lang.reflect.Field;
import java.util.List;

import static wechat.app.bean.message.category.card.CardPayOrderEvent.*;

/**
 * Created by Administrator on 2016/3/7.
 * 文档：http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
 *       http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html
 */


public class Message {
    public enum MsgTypeEnum{text,image,voice,video,shortvideo,location,link,event};
    public enum EventEnum{subscribe,unsubscribe,SCAN,LOCATION,CLICK,VIEW,kf_create_session,kf_close_session,kf_switch_session,
        MASSSENDJOBFINISH,TEMPLATESENDJOBFINISH,poi_check_notify,
        card_pass_check,card_not_pass_check,user_get_card,user_del_card,user_consume_card,user_pay_from_pay_cell,user_view_card,user_enter_session_from_card,update_member_card,card_sku_remind,card_pay_order,merchant_order};


    //开发者微信号
    public String ToUserName = null;
    //发送方帐号（一个OpenID）
    public String FromUserName = null;
    //消息创建时间 （整型）
    public long CreateTime;
    //text,image,voice,video,shortvideo,location,link,event
    public MsgTypeEnum MsgType;
    //消息id，64位整型
    public long MsgId; // TODO: MsgId记录下是否处理过或者在处理中,避免重复处理

    public String Encrypt;

    //文本消息
    public String Content = null;


    //图片消息,语音消息,视频消息
    //消息id，可以调用多媒体文件下载接口拉取数据。
    public String MediaId;
    //图片链接
    public String PicUrl;
    //语音格式，如amr，speex等
    public String Format;
    //请注意，开通语音识别后，用户每次发送语音给公众号时，微信会在推送的语音消息XML数据包中，增加一个Recongnition字段（注：由于客户端缓存，开发者开启或者关闭语音识别功能，对新关注者立刻生效，对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试）
    public String Recongnition;

    //视频消息缩略图的媒体id，可以调用多媒体文件下载接口拉取数据。
    public String ThumbMediaId;

    //地理位置消息
    //地理位置维度
    public float Location_X;
    //地理位置经度
    public float Location_Y;
    //地图缩放大小
    public int Scale;
    //地理位置信息
    public String Label;

    //链接消息
    //消息标题
    public String Title;
    //消息描述
    public String Description;
    //消息链接
    public String Url;

    //---------------------------事件消息-------------------------------
    //事件类型，subscribe(订阅)、unsubscribe(取消订阅)，SCAN（扫描带参数二维码事件），LOCATION（上报地理位置事件），CLICK（点击菜单拉取消息时的事件推送），VIEW（点击菜单跳转链接时的事件推送）
    public EventEnum Event;
    public String EventKey;
    public String signature;

    //扫描带参数二维码事件
    public String Ticket;

    //加入公众号开了地理位置获取，并且用户同意获取
    //只有用户点击进入公众号，才会出现一次，后续的点击菜单，输入数据等都不会有，返回0
    public String Latitude;
    public String Longitude;
    public String Precision;

    public String KfAccount;


    //群发信息
    public int MsgID;
    public String Status;
    public int TotalCount;
    public int FilterCount;
    public int SentCount;
    public int ErrorCount;

    //卡劵信息
    public String CardId;
    public String OrderId;
    public String PayFinishTime;
    public String Desc;
    public int FreeCoinCount;
    public int PayCoinCount;
    public int RefundFreeCoinCount;
    public int RefundPayCoinCount;
    public String OrderType;
    public String Memo;
    public String ReceiptInfo;
    public String Detail;
    public int ModifyBonus;
    public int ModifyBalance;
    public String UserCardCode;
    public String ConsumeSource;
    public String LocationId;
    public String StaffOpenId;
    public String IsGiveByFriend;
    public String OldUserCardCode;
    public String OuterId;
    public String FriendUserName;
    public String TransId;
    public String Fee;
    public String OriginalFee;


    //订单信息
//    public String OrderId;
    public String OrderStatus;
    public String ProductId;
    public String SkuInfo;

    public static Message fromXml(String msg_signature,String timestampStr,String nonce, Document dom,String token,String encodingAesKey,String appId){
        if (dom == null) {
            return null;
        }
        Message message = new Message();
        DataFormatUtil.scalaNodeToObject(message, dom);

        if(message.Encrypt!=null){
            String EncryptStr = message.Encrypt;
            try {
                WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
                String format = "<xml><ToUserName>"+message.ToUserName+"</ToUserName><Encrypt>"+message.Encrypt+"</Encrypt></xml>";
                String result = pc.decryptMsg(msg_signature, timestampStr, nonce, format);
                try {
                    message = JSON.parseObject(DataFormatUtil.xmlStrToJSONObjectSimple(result).toJSONString(),Message.class);
                    message.Encrypt = EncryptStr;
                } catch (DocumentException e) {
                    e.printStackTrace();
                }
            } catch (AesException e) {
                e.printStackTrace();
            }
        }
        return message;
    }

    public void print(){
        List<Field> fields = Common.getFields(this);
        for(Field field :fields){
            if(Common.getPropertyOfObject(this,field.getName())!=null){
                System.out.println(field.getName()+":"+Common.getPropertyOfObject(this,field.getName()));
            }
        }
    }



}
